MeasurementErrorVariance4th Dimension (~Pascal) Code for compute means of logs, Measurement Error Variance, and SDs of morpho characters, for each species  // ----------------------------------------------------  // User name (OS): Robert K. Colwell  // Date and time: 08/27/15, 16:50:15  // Revised: 06/14/20 and 12/10/22  // ----------------------------------------------------  // Method: MeasurementErrorVariance  // Description  // Runs the code, using three consecutive procedures, to compute means of logs, Measurement Error Variance,  //     and SDs of morpho characters, for each species  // ----------------------------------------------------LoadDataTable GetSpeciesMeansAndSDs ExportSpeciesMeansAndSDs   // ----------------------------------------------------  // User name (OS): Robert K. Colwell  // Date and time: 08/27/15, 15:54:17  // Revised: 06/14/20 and 12/10/22  // ----------------------------------------------------  // Method: LoadDataTable  // Description: Reads the raw specimen data into arrays  // C_TEXT(Line)DocNo:=Open document("")If (DocNo#�00:00:00�)Line:=ReadRecord   //Parameter recordNumberRecords:=Num(NextField)  //Number of records to readNumberColumns:=Num(NextField) //Number of DATA columns to read; elevation and MTC will be read but ignoredNumberColumns:=11  //OverrideSexCode:=Num(NextField)  //0 for all specimens, 1 for males only, 2 for females onlyARRAY REAL(<>SpecimenRecords;NumberRecords;11)ARRAY TEXT(<>ColumnHeaders;11)ARRAY TEXT(<>SpecimenGenusSpecies;NumberRecords)ARRAY TEXT(<>SpecimenAlphaCode;NumberRecords)ARRAY INTEGER(<>SpecimenSpeciesNumber;NumberRecords)ARRAY INTEGER(<>SpecimenSexCode;NumberRecords)C_REAL($Elevation)Line:=ReadRecord   //Header recordFor ($j;1;4) //Read headers for Species name, alpha code, species number, and sex code<>ColumnHeaders{$j}:=NextField End for   //($j;1;NumberColumns)$Elevation:=num(NextField)  //Elevation. Ignored but must be read to advance NextFieldFor ($j;5;11)  //Read headers for morpho measurements, excecpt for MTC<>ColumnHeaders{$j}:=NextField End for   //($j;5;11)For ($i;1;NumberRecords)  //Get the data recordsLine:=ReadRecord <>SpecimenGenusSpecies{$i}:= NextField //Sp name<>SpecimenAlphaCode{$i}:= NextField //Alpha code<>SpecimenSpeciesNumber{$i}:=num(NextField)   //Sp Number code<>SpecimenSexCode{$i}:=Num(NextField)  //Sex code$Elevation:=num(NextField)   //Elevation. Ignored but must be read to advance NextFieldFor ($j;1;7)<>SpecimenRecords{$i}{$j}:=Num(NextField )End for   //($j;1;NumberColumns) End for   //   ($i;1;$NRecords)   End if   //($Test="Error")   CLOSE DOCUMENT(DocNo)  // ----------------------------------------------------  // User name (OS): Robert K. Colwell  // Date and time: 08/27/15, 15:59:31  // ----------------------------------------------------  // Method: ReadRecord  // Description: Reads one record  // ----------------------------------------------------<>EndField:=Char(9)  //Sets field delimiter for import; Char(9) is Tab<>CR:=Char(13). ////Sets line delimiter for import; Char(13) is EndLineC_TEXT($Line)RECEIVE PACKET(DocNo;$Line;Char(13))  //Get one  record from the file; stop char (rec delimiter) not returned                   // ----------------------------------------------------  // User name (OS): Robert K. Colwell  // Date and time: 08/27/15, 16:08:38  // ----------------------------------------------------  // Method: NextField  // Description: Extracts the next field from the record just read    // ----------------------------------------------------$NextFldEnd:=Position(<>EndField;Line)  //Find the next field delimiterIf ($NextFldEnd>=1)  //Allow blanks as zeroes$0:=Substring(Line;1;$NextFldEnd-1)  //Get all chars up to next field delimiterLine:=Substring(Line;$NextFldEnd+1)  //Strip off chars, including field delimiter, up to the next field      Else   //Missing data: Too many fields specified $0:="Error"  //Error codeEnd if   // ($NextFldEnd�#�0)  // ----------------------------------------------------  // User name (OS): Robert K. Colwell  // Date: 07/17/21  // Revised: 12/10/22  // ----------------------------------------------------  // Method: GetSpeciesMeansAndSDs  // Description: With log transform as of 07/19/21  // ----------------------------------------------------ARRAY TEXT(<>GenusSpecies;0)ARRAY TEXT(<>SpeciesAlphaCode;0)ARRAY INTEGER(<>SpeciesNumber;0)ARRAY REAL(<>SpeciesMeans;0;NumberColumns)  ARRAY REAL(<>SpeciesSDs;0;NumberColumns)  ARRAY REAL(<>SampleSizes;0;NumberColumns)  //DATA COLUMNS IN INPUT:  //GenusSpecies AlphaSpCode  NumSpCode  SexCode    //Weight  Wing ExposedCulmen  TotalCulmen Tarsus  HalluxClaw  HalluxToeARRAY REAL(<>WeightedVarSum;NumberColumns)  //To accumulate var/ni sum for Error VarARRAY REAL(<>CharacterMeans;NumberColumns)  //To compute sums of means among species for each characterARRAY REAL(<>CharacterNatVars;NumberColumns)  //To compute sums of squares of means among species for each characterC_Integer($PreviousSpecimenSpNum)$PreviousSpecimenSpNum:=0  //InitializeSpeciesIndex:=0  //InitializeFor ($Rec;1;NumberRecords)  //Go through spcm recsIf ((SexCode=0) | (<>SpecimenRecords{$Rec}{3}=SexCode))  //If SexCode=0, use all recs, SexCode=1 for males only, SexCode=2 for females only  //Second Boolean sorts out female and male, if specifiedIf (<>SpecimenSpeciesNumber{$Rec}#$PreviousSpecimenSpNum)  //New species, based on SpNumCodeSpeciesIndex:=SpeciesIndex+1INSERT IN ARRAY(<>GenusSpecies;SpeciesIndex)  //Enlarge the arrays by one elementINSERT IN ARRAY(<>SpeciesAlphaCode;SpeciesIndex)INSERT IN ARRAY(<>SpeciesNumber;SpeciesIndex)INSERT IN ARRAY(<>SpeciesNumber;SpeciesIndex;NumberColumns)  //Enlarge the arrays by one elementINSERT IN ARRAY(<>SpeciesMeans;SpeciesIndex;NumberColumns)INSERT IN ARRAY(<>SpeciesSDs;SpeciesIndex;NumberColumns)INSERT IN ARRAY(<>SampleSizes;SpeciesIndex;NumberColumns)$PreviousSpecimenSpNum:=<>SpecimenSpeciesNumber{$Rec}  //Update current species numerical code<>GenusSpecies{SpeciesIndex}:=<>SpecimenGenusSpecies{$Rec}<>SpeciesAlphaCode{SpeciesIndex}:=<>SpecimenAlphaCode{$Rec}<>SpeciesNumber{SpeciesIndex}:=<>SpecimenSpeciesNumber{$Rec}  //SpAlphaCodeFor ($j;1;NumberColumns)  //Data columns  xxxxx $Variate:=<>SpecimenRecords{$Rec}{$j}  //Get the next variateIf ($Variate=0)<>SpeciesMeans{SpeciesIndex}{$j}:=0<>SpeciesSDs{SpeciesIndex}{$j}:=0Else <>SpeciesMeans{SpeciesIndex}{$j}:=Log($Variate)  //First spcm of a new sp; get ln of its value<>SpeciesSDs{SpeciesIndex}{$j}:=Log($Variate)*Log($Variate)  //First spcm of a new sp;   //square the ln of its valueEnd if   //($Variate=0)Case of : (<>SpecimenRecords{$Rec}{$j}>0)  //Metric fields only<>SampleSizes{SpeciesIndex}{$j}:=1  //Count the first non-zero specimen of this new species: (<>SpecimenRecords{$Rec}{$j}=0)  //Metric fields only<>SampleSizes{SpeciesIndex}{$j}:=0  //Don't count it if not > 0End case   //(($j>3)&(<>SpecimenRecords{$Rec}{$j}>0))End for   //($j;2;NumberColumns)Else   //Another specimen of the same speciesFor ($j;1;NumberColumns)  //Metric fields only$Variate:=<>SpecimenRecords{$Rec}{$j}  //Get the next variateIf ($Variate>0)<>SpeciesMeans{SpeciesIndex}{$j}:=<>SpeciesMeans{SpeciesIndex}{$j}+Log($Variate)<>SpeciesSDs{SpeciesIndex}{$j}:=<>SpeciesSDs{SpeciesIndex}{$j}+(Log($Variate)*Log($Variate))<>SampleSizes{SpeciesIndex}{$j}:=<>SampleSizes{SpeciesIndex}{$j}+1End if   //($Variate>0) //Must skip empty recs (with zero values)End for   //($j;3;NumberColumns)End if   //(<>SpecimenRecords{$Rec}{1})#$PreviousSpNum) End if   //((SexCode=0) | (<>SpecimenRecords{$Rec}{3}=SexCode))  End for   //($Rec;1;NumberRecords)C_REAL($Sum;$SumSquared;$Mean;$Variance)C_LONGINT($N;$NonZeroN;$GTOneN)ARRAY REAL(<>NonZeroCount;NumberColumns)ARRAY REAL(<>GTOneCount;NumberColumns)  //Initialize character stats: Metric fields onlyFor ($j;1;NumberColumns)<>WeightedVarSum{$j}:=0<>CharacterMeans{$j}:=0<>CharacterNatVars{$j}:=0End for   //($j;NumberColumns)  //Compute species statsFor ($i;1;SpeciesIndex)For ($j;1;NumberColumns)  //Metric fields onlyIf (<>SampleSizes{$i}{$j}>0)$Sum:=<>SpeciesMeans{$i}{$j}$SumSquared:=<>SpeciesSDs{$i}{$j}$N:=<>SampleSizes{$i}{$j}$Mean:=$Sum/$N<>SpeciesMeans{$i}{$j}:=$Mean<>CharacterMeans{$j}:=<>CharacterMeans{$j}+$Mean<>CharacterNatVars{$j}:=<>CharacterNatVars{$j}+($Mean*$Mean)  //*******If ($N>1)$Variance:=($SumSquared-(($Sum*$Sum)/$N))/($N-1)<>WeightedVarSum{$j}:=<>WeightedVarSum{$j}+($Variance/$N)<>SpeciesSDs{$i}{$j}:=Square root($Variance)Else <>SpeciesSDs{$i}{$j}:=0End if   //($N>1)  //<>SpeciesSDs{$i}{$j}:=ComputeSD ($N;$Sum;$SumSquared)End if   //(<>SampleSizes{$i}{$j}>0)End for   //($j;3;NumberColumns)End for   //($i;1;SpeciesIndex)  //Compute character variancesFor ($j;1;NumberColumns)$NonZeroN:=0$GTOneN:=0For ($i;1;SpeciesIndex)If (<>SampleSizes{$i}{$j}>0)$NonZeroN:=$NonZeroN+1End if   //(<>SampleSizes{$i}{$j}>0)If (<>SampleSizes{$i}{$j}>1)$GTOneN:=$GTOneN+1End if   //(<>SampleSizes{$i}{$j}>0)End for   //($i;1;SpeciesIndex)$Sum:=<>CharacterMeans{$j}$SumSquared:=<>CharacterNatVars{$j}$N:=$NonZeroN$Variance:=($SumSquared-(($Sum*$Sum)/$N))/($N-1)<>CharacterNatVars{$j}:=$Variance<>CharacterMeans{$j}:=$Sum/$N<>WeightedVarSum{$j}:=<>WeightedVarSum{$j}/$GTOneN  //Count only if Ni > 1<>NonZeroCount{$j}:=$NonZeroN  //Save sample sizes for NatVar<>GTOneCount{$j}:=$GTOneN  //Save sample sizes for Weighted Error VarEnd for   //($j;4;NumberColumns)  //Compute character variances  // ----------------------------------------------------  // User name (OS): Robert K. Colwell  // Date: 07/24/21  // Revised: 12/10/22  // ----------------------------------------------------  // Method: ExportSpeciesMeansAndSDs  // Description: Exports results by character and by species  // ----------------------------------------------------Case of : (SexCode=0)$SexCodeText:="All Specimens ": (SexCode=1)$SexCodeText:="Male Specimens ": (SexCode=2)$SexCodeText:="Female Specimens "End case   //(SexCode=0)$DatasetTitle:="Measurement error variance for hummingbird morpological data (log transformed) for "+$SexCodeText  $DocNo:=Create document("")//CHARACTER BY CHARACTER RESULTS (SUMMARY OVER ALL SPECIES)If ($DocNo#�00:00:00�)$Line:=$DatasetTitle+String(Current date;6)+<>EndLine$Line:=$Line+"Character variance stats"+<>EndField+<>EndField+<>EndField  //Add 2 empty columnsFor ($j;5;11)$ColHead:=<>ColumnHeaders{$j}$Line:=$Line+$ColHead+" Char Mean"+<>EndField+$ColHead+" Total Var"+<>EndField+$ColHead+" Meas Var"+<>EndFieldEnd for   //($j;1;NumberColumns)SEND PACKET($DocNo;$Line+<>EndLine)  //Send Headers for Variance output$Line:=<>EndField+<>EndField+"Variance"+<>EndFieldFor ($j;1;7)$Line:=$Line+String(<>CharacterMeans{$j})+<>EndField+String(<>CharacterNatVars{$j})+<>EndField+String(<>WeightedVarSum{$j})+<>EndFieldEnd for   //($j;1;NumberColumns)SEND PACKET($DocNo;$Line+<>EndLine)  //Send results for Variance output$Line:=<>EndField+<>EndField+"Count (n)"+<>EndFieldFor ($j;1;7)$Line:=$Line+String(<>NonZeroCount{$j})+<>EndField+String(<>NonZeroCount{$j})+<>EndField+String(<>GTOneCount{$j})+<>EndFieldEnd for   //($j;1;NumberColumns)SEND PACKET($DocNo;$Line+<>EndLine+<>EndLine)  //Send results for Variance output//SPECIES BY SPECIES RESULTS$Line:=""For ($j;1;4)$Line:=$Line+<>ColumnHeaders{$j}+<>EndField  //Species SpAlphaCode, SpNumCode, and SexCodeEnd for   //($j;1;3)For ($j;5;11)$Line:=$Line+<>ColumnHeaders{$j}+" Mean"+<>EndField+<>ColumnHeaders{$j}+" SD"+<>EndField+<>ColumnHeaders{$j}+" N"+<>EndFieldEnd for   //($j;1;NumberColumns)SEND PACKET($DocNo;$Line+<>EndLine)  //Send HeadersFor ($i;1;SpeciesIndex)  //SpeciesIndex last updated as final line number$Line:=<>GenusSpecies{$i}+<>EndField+<>SpeciesAlphaCode{$i}+<>EndField+String(<>SpeciesNumber{$i})+<>EndField+String(SexCode)+<>EndField  //SexCode from parameterFor ($j;1;7)$Line:=$Line+String(<>SpeciesMeans{$i}{$j})+<>EndField+String(<>SpeciesSDs{$i}{$j})+<>EndField+String(<>SampleSizes{$i}{$j})+<>EndFieldEnd for   //($j;3;NumberColumns)SEND PACKET($DocNo;$Line+<>EndLine)  //Send data lineEnd for   //($i;1;$MeanRecordNum)CLOSE DOCUMENT($DocNo)ALERT("Results were successfully exported.")Else ALERT("Error:  The output file was not written. Try again.")End if   //�`DocNo=..    